/*
 * @description:
 * @author: <a href="mailto:joshualwork@163.com">joshua_liu</a>
 * @Date: 2024-03-07 22:31:08
 * @FilePath: \dynamic-conf\loader\localGlobal.go
 * @LastEditTime: 2024-03-20 00:02:10
 * @LastEditors: <a href="mailto:joshualwork@163.com">joshua_liu</a>
 */
package loader

import (
	"flag"
	"fmt"
	"strings"

	log "github.com/sirupsen/logrus"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var GlobalConfig *viper.Viper

func init() {
	log.Info("Loading configuration logics...\n")
	GlobalConfig = loadConfig()
}

func loadConfig() *viper.Viper {
	GlobalConfig := viper.New()
	GlobalConfig.AutomaticEnv()
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.String("f", "", "Dynamic config input start application config file.")
	pflag.Int("p", 18090, "The port of dynamic-conf to listen for HTTP requests from input. ")
	pflag.Parse()
	GlobalConfig.BindPFlags(pflag.CommandLine)
	cmdFile := GlobalConfig.GetString("f")
	if cmdFile != "" {
		// SetConfigFile 显式定义配置文件的路径、名称和扩展名。
		// Viper 将使用它而不检查任何配置路径。
		log.Info(fmt.Sprintf("Use cmd config file: '%s'\n", cmdFile))
		GlobalConfig.SetConfigFile(cmdFile)
	} else {
		// 如果没有显式指定配置文件，则
		// 会去下面的路径里找文件名`application`的文件  name of config file (without extension)
		// 按照 []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}的顺序(居然还支持Java用的properties)
		GlobalConfig.SetConfigName("application")
		GlobalConfig.AddConfigPath("/etc/dynamic-conf/") // 找寻的路径
		GlobalConfig.AddConfigPath("$HOME/.dynamic-conf/")
		GlobalConfig.AddConfigPath("./config/")
	}
	err := GlobalConfig.ReadInConfig()
	if err != nil {
		log.Panic(fmt.Sprintf("Error reading config: %s", err))
	}
	if GlobalConfig.IsSet("application.port") {
		GlobalConfig.Set("p", GlobalConfig.GetInt("application.port"))
	}
	for _, k := range GlobalConfig.AllKeys() {
		value := GlobalConfig.GetString(k)
		if strings.HasPrefix(value, "${") && strings.HasSuffix(value, "}") {
			realKey := strings.TrimSuffix(strings.TrimPrefix(value, "${"), "}")
			dftRealval := ""
			if strings.Contains(realKey, ":") {
				parts := strings.Split(realKey, ":")
				if len(parts) == 2 {
					realKey = parts[0]
					dftRealval = parts[1]
				}
			}
			if GlobalConfig.IsSet(realKey) {
				GlobalConfig.Set(k, GlobalConfig.GetString(realKey))
			} else {
				GlobalConfig.Set(k, dftRealval)
			}
		}
	}
	// GlobalConfig.WatchConfig()
	// GlobalConfig.OnConfigChange(func(e fsnotify.Event) {
	// 	// 配置文件发生变更之后会调用的回调函数
	// 	log.Info(fmt.Sprintf("Config file changed: '%s' \n", e.Name))
	// })
	log.Info(fmt.Sprintf("Use config file: '%s'\n", GlobalConfig.ConfigFileUsed()))
	log.Info(fmt.Sprintf("Dynamic config type: '%s'\n", GlobalConfig.GetString("application.config.middle-ware.type")))
	return GlobalConfig
}
